#pragma once
#include <iostream>
#include <sys/socket.h>
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"
const int gmaxsize = 1024;
using namespace Protocol;
class HandlerEvent
{
private:
    static void HandlerRequest(ConnectionPtr conn)
    {
        // 将结果放到outbuffer里面统一发
        std::string &inbuffer = conn->inbuffer();
        std::string msg;
        while (Decode(inbuffer, &msg))
        {
            // 解析完毕msg放着就是完整的报文了
            auto req = Factory::BuildRequest();
            // 反序列化
            if (!req->DeSerialize(msg))
            {
                // ELOG("反序列化失败!");
                continue;
            }
            // 计算结果
            auto resp = Calculate().Cal(req);
            std::string respstr;
            // 序列化
            resp->Serialize(&respstr);
            // 封装报头
            respstr = Encode(respstr);
            // 添加到conn的接收缓冲区
            conn->AddOutbuffer(respstr.c_str());
        }

        // 发送
        if (!conn->OutBufferEmpty())
        {
            // 直接发 ，有问题才考虑处理异常
            conn->_sender(conn);
        }
    }

public:
    static void recver(ConnectionPtr conn)
    {
        errno = 0;
        // 读取,循环读
        char buffer[gmaxsize];

        while (true)
        {
            int n = recv(conn->GetSockfd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                // 读取到数据了，添加到缓冲区中
                buffer[n] = 0;
                conn->AddInbuffer(buffer);
            }
            else
            {
                if (errno == EAGAIN)
                    break;
                if (errno == EINTR)
                    continue;
                else
                {
                    ILOG("发生异常事件,当前文件是%d", conn->GetSockfd());
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        std::cout << conn->inbuffer();
        // 尝试开始分析报文
        HandlerRequest(conn);
    }
    static void sender(ConnectionPtr conn)
    {
        errno = 0;
        std::string outbuffer = conn->outbuffer();
        while (true)
        {
            int n = send(conn->GetSockfd(), outbuffer.c_str(), outbuffer.size(), 0);
            if (n >= 0)
            {
                outbuffer.erase(0, n);
                if (outbuffer.empty())
                    break;
            }
            else
            {
                if (errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    ILOG("发生异常事件,当前文件是%d", conn->GetSockfd());
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        // 读到这里说明？发送缓冲区满了，需要交给epoll关心
        // 开启epoll关心事件
        if (outbuffer.size())
        {
            conn->_R->EnableReadWirte(conn->GetSockfd(), true, true);
        }
        else
        {
            conn->_R->EnableReadWirte(conn->GetSockfd(), true, false);
        }
    }
    static void excepter(ConnectionPtr conn)
    {
        ILOG("正在关闭....who:%d",conn->GetSockfd());
        errno = 0;
        // 做什么？关闭连接
        // 1.取消内核关心 2.关闭conn 3.close 4.delete conn
        conn->_R->DelConnection(conn->GetSockfd());
        conn->Close();
    }
};